package cn.com.libertymutual.saleplat.config;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;

import javax.annotation.Resource;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.access.ExceptionTranslationFilter;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.csrf.CsrfToken;
import org.springframework.security.web.csrf.CsrfTokenRepository;
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.WebUtils;

import cn.com.libertymutual.core.base.dto.UserInfo;
import cn.com.libertymutual.core.util.BeanUtilExt;
import cn.com.libertymutual.core.util.Constants;
import cn.com.libertymutual.core.util.Current;
import cn.com.libertymutual.core.web.util.RequestUtils;
import cn.com.libertymutual.core.web.util.ResponseUtils;
import cn.com.libertymutual.sp.bean.SysOperationLog;
import cn.com.libertymutual.sp.dao.OperationLogDao;
import cn.com.libertymutual.sys.bean.SysUser;
import cn.com.libertymutual.sys.dao.ISysUserDao;
import cn.com.libertymutual.sys.service.api.ISysUserService;
import cn.com.libertymutual.web.filter.SessionFilter;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class BootstrapSecurityConfig extends WebSecurityConfigurerAdapter {
	private static Logger log = LoggerFactory.getLogger(BootstrapSecurityConfig.class);
	// @Value("${ldap.domain}")
	// private String DOMAIN;

	// @Value("${ldap.url}")
	// private String URL;

	@Value("${studio.excludeuri}")
	private String excludeUri;
	@Autowired
	private OperationLogDao operationLogDao;
	@Resource
	private ISysUserService sysUserService;
	@Resource
	private ISysUserDao iSysUserDao;
	@Resource
	private LadpAuthProvider ladpAuthProvider;
	// @Resource private IUserInfoService userInfoService;

	////////// 20180202@Autowired private JwtAuthenticationEntryPoint
	////////// unauthorizedHandler;
	//////////////// @Autowired private JwtAuthenticationTokenFilter
	////////// jwtAuthenticationTokenFilter;

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.csrf().disable();

		System.out.println(excludeUri);

		http.authorizeRequests().antMatchers(excludeUri.split(",")).permitAll()
				// .and().formLogin().loginProcessingUrl("/login").permitAll().and().exceptionHandling().authenticationEntryPoint(unauthorizedHandler)

				.anyRequest().authenticated()
				/*
				 * .and() .csrf().csrfTokenRepository(csrfTokenRepository()) .and()
				 * .addFilterAfter(csrfHeaderFilter(), CsrfFilter.class)
				 */

				.and()
				// .addFilterBefore(sessionFilter(),
				// UsernamePasswordAuthenticationFilter.class);
				.addFilterAfter(new SessionFilter().excludeUri(excludeUri.split(",")), ExceptionTranslationFilter.class)
		// .authorizeRequests()
		/*** disabled by bob.kuang 20171206 **
		.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class)
		.exceptionHandling().authenticationEntryPoint(unauthorizedHandler)
		.and().authorizeRequests() ****/
		;

		// http.authorizeRequests().and().formLogin().loginProcessingUrl("/login.html").permitAll();
		// http.authorizeRequests().and().formLogin().loginPage("/login.html")
		http.authorizeRequests().and().formLogin().loginPage("/")
				// http.authorizeRequests().and().formLogin().loginPage("/index.html")
				.failureUrl("/web/loginFailure").loginProcessingUrl("/web/login").permitAll().successForwardUrl("/web/index")
				.usernameParameter("username").passwordParameter("password").successHandler(new AuthenticationSuccessHandler() {
					@Override
					public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
							throws IOException, ServletException {
						response.addHeader("success", "true");
						UserInfo userInfo = null;
						try {
							String reg = "^(\\-|\\+)?\\d+(\\.\\d+)?$";
							Current.IP.set(RequestUtils.getIpAddr(request));
							log.info("----------authentication.getPrincipal:{}",(String) authentication.getPrincipal());
							if (Pattern.compile(reg).matcher((String) authentication.getPrincipal()).find()) {
								log.info("手机号登录后台！");
								List<SysUser> dbsysuser = iSysUserDao.findByMobile((String) authentication.getPrincipal());
								if (CollectionUtils.isNotEmpty(dbsysuser)) {
									userInfo = sysUserService.initUser(dbsysuser.get(0).getUserid());
								}
							} else {
								userInfo = sysUserService.initUser((String) authentication.getPrincipal());
							}
							request.getSession(true).setAttribute(Constants.USER_INFO_KEY, userInfo);
							Current.userInfo.set(userInfo);
							if (userInfo != null) {
								Current.userId.set(userInfo.getUserId());
								SysOperationLog operLog = new SysOperationLog();
								operLog.setIP(RequestUtils.getIpAddr(request));
								operLog.setLevel("1");
								operLog.setModule("管理员登录");
								operLog.setOperationTime(new Date());
								operLog.setUserId(userInfo.getUserId());
								operLog.setContent(userInfo.getUserId() + "登录成功！");
								operationLogDao.save(operLog);
							}
							// response.addHeader("userInfo", BeanUtilExt.toJsonString(userInfo));
							ResponseUtils.renderJson(response, BeanUtilExt.toJsonString(userInfo));
							System.out.println(response.getHeader("success"));
						} catch (Exception e) {
							log.error("登录异常:", e);
							response.addHeader("errorMsg", URLEncoder.encode(e.getMessage(), "UTF-8"));
							response.addHeader("success", "false");
						}

						// response.getWriter().append(arg0)
					}
				}).failureHandler(new AuthenticationFailureHandler() {

					@Override
					public void onAuthenticationFailure(HttpServletRequest arg0, HttpServletResponse response, AuthenticationException arg2)
							throws IOException, ServletException {
						response.addHeader("errorMsg", URLEncoder.encode("登录失败", "UTF-8"));
						response.addHeader("success", "false");
					}
				})
				/*
				 * Use HTTPs for ALL requests
				 */
				/// http.requiresChannel().anyRequest().requiresSecure();

				/// http.portMapper().http(httpPort).mapsTo(httpsPort);
				.and().logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout", "GET")).logoutSuccessUrl("/login.html")
				.invalidateHttpSession(true).addLogoutHandler(new LogoutHandler() {

					@Override
					public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
						// TODO Auto-generated method stub
						if (authentication != null && authentication.getCredentials() != null)
							System.out.println(authentication.getCredentials() + "登出.");
					}

				}).logoutSuccessHandler(new LogoutSuccessHandler() {

					@Override
					public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
							throws IOException, ServletException {

						request.getSession().invalidate();
						// request.getRequestDispatcher("/login.html").forward(request, response);
						// request.getRequestDispatcher("/index.html").forward(request, response);
						request.getRequestDispatcher("/").forward(request, response);
					}
				});
	}

	@Override
	protected void configure(AuthenticationManagerBuilder authManagerBuilder) throws Exception {
		/// authManagerBuilder.authenticationProvider(activeDirectoryLdapAuthenticationProvider()).userDetailsService(userDetailsService());

		authManagerBuilder.authenticationProvider(ladpAuthProvider);// .userDetailsService(userDetailsService);
	}

	/*
	 * @Bean public AuthenticationManager authenticationManager() { return new
	 * ProviderManager(Arrays.asList(activeDirectoryLdapAuthenticationProvider()));
	 * }
	 * 
	 * @Bean public AuthenticationProvider
	 * activeDirectoryLdapAuthenticationProvider() {
	 * ActiveDirectoryLdapAuthenticationProvider provider = new
	 * ActiveDirectoryLdapAuthenticationProvider(DOMAIN, URL);
	 * provider.setConvertSubErrorCodesToExceptions(true);
	 * provider.setUseAuthenticationRequestCredentials(true);
	 * provider.setUserDetailsContextMapper(userDetailsContextMapper());
	 * 
	 * return provider; }
	 * 
	 * @Bean public UserDetailsContextMapper userDetailsContextMapper() {
	 * UserDetailsContextMapper contextMapper = new CustomUserDetailServiceImpl();
	 * 
	 * return contextMapper; }
	 */

	/*
	 * @Configuration protected static class AuthenticationConfiguration extends
	 * GlobalAuthenticationConfigurerAdapter {
	 * 
	 * @Override public void init(AuthenticationManagerBuilder auth) throws
	 * Exception { auth .ldapAuthentication() .userDnPatterns("sAMAccountName={0}")
	 * .groupSearchBase( DOMAIN ) .contextSource().url(URL).managerDn(DOMAIN); } }
	 */

	@SuppressWarnings("unused")
	private Filter csrfHeaderFilter() {
		return new OncePerRequestFilter() {
			@Override
			protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
					throws ServletException, IOException {
				CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
				if (csrf != null) {
					Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
					String token = csrf.getToken();
					if (cookie == null || token != null && !token.equals(cookie.getValue())) {
						cookie = new Cookie("XSRF-TOKEN", token);
						cookie.setPath("/");
						response.addCookie(cookie);
					}
				}
				filterChain.doFilter(request, response);
			}
		};
	}

	@SuppressWarnings("unused")
	private CsrfTokenRepository csrfTokenRepository() {
		HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
		repository.setHeaderName("X-XSRF-TOKEN");
		return repository;
	}

}
